﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ST.Common.Util.Model;
using ST.Common.Util.Security;
using ST.Common.Util.Text;
using System;
using System.Reflection;

namespace ST.Common.Util.Mvc
{
	public static class HttpRequestExtensions
	{
		/// <summary>
		/// 获取当前请求的完整路径
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetRequestUrl(this HttpRequest request)
		{
			return string.Concat(request.Scheme,
							"://",
							request.Host.ToUriComponent(),
							request.PathBase.ToUriComponent(),
							request.Path.ToUriComponent(),
							request.QueryString.ToUriComponent());
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetDisplayUrl(HttpRequest request)
		{
			return request.GetDisplayUrl();
		}

		/// <summary>
		/// 获取当前请求的Url前缀（包含PathBase）
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetRequestDomainBase(this HttpRequest request, bool formatLocal = false)
		{
			if (!formatLocal)
			{
				return string.Concat(request.Scheme,
							"://",
							request.Host.ToUriComponent(),
							request.PathBase.ToUriComponent());
			}
			else
			{
				var host = request.Host.Host;
				switch (host)
				{
					case "localhost":
					case "127.0.0.1":
					case "::1":
						host = EnvironmentHelper.GetLocalIP();
						break;
				}
				return string.Concat(request.Scheme,
							"://",
							host,
							request.Host.Port.HasValue && request.Host.Port.Value > 0 ? ":" + request.Host.Port.Value : "",
							request.PathBase.ToUriComponent());
			}
		}

		/// <summary>
		/// 获取get请求参数
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="request"></param>
		/// <returns></returns>
		public static T GetSearchModelFromGet<T>(this HttpRequest request)
			where T : BaseSearchModel, new()
		{
			var vms = new T();
			PropertyInfo[] properties = typeof(T).GetProperties();
			foreach (PropertyInfo p in properties)
			{
				if (!p.CanWrite || request.Query[p.Name] == StringValues.Empty)
				{
					continue;
				}
				if (p.PropertyType == typeof(string))
				{
					p.SetValue(vms, TextHelper.GetString(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(bool))
				{
					p.SetValue(vms, TextHelper.GetBool(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(bool?))
				{
					p.SetValue(vms, TextHelper.GetBoolNullable(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(int))
				{
					p.SetValue(vms, TextHelper.GetInt(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(int?))
				{
					p.SetValue(vms, TextHelper.GetIntNullable(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(int[]))
				{
					p.SetValue(vms, TextHelper.GetInts(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(long))
				{
					p.SetValue(vms, TextHelper.GetInt64(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(long?))
				{
					p.SetValue(vms, TextHelper.GetInt64Nullable(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(long[]))
				{
					p.SetValue(vms, TextHelper.GetInt64s(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(decimal))
				{
					p.SetValue(vms, TextHelper.GetDecimal(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(decimal?))
				{
					p.SetValue(vms, TextHelper.GetDecimalNullable(request.Query[p.Name]));
				}
				else if (p.PropertyType == typeof(DateTime))
				{
					if (p.Name.EndsWith("_e"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeEnd(request.Query[p.Name]));
					}
					else if (p.Name.EndsWith("_s"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeStart(request.Query[p.Name]));
					}
					else
					{
						p.SetValue(vms, TextHelper.GetDateTime(request.Query[p.Name]));
					}
				}
			}
			return vms;
		}

		/// <summary>
		/// 获取get请求参数
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="request"></param>
		/// <returns></returns>
		public static T GetSearchModelFromPost<T>(this HttpRequest request)
			where T : BaseSearchModel, new()
		{
			T vms = new T();
			Type t = vms.GetType();
			var properties = t.GetProperties();
			foreach (var p in properties)
			{
				if (!p.CanWrite || request.Form[p.Name] == StringValues.Empty && request.Form[p.Name + "[]"] == StringValues.Empty)
				{
					continue;
				}
				if (p.PropertyType == typeof(string))
				{
					p.SetValue(vms, TextHelper.GetString(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(bool))
				{
					p.SetValue(vms, TextHelper.GetBool(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(bool?))
				{
					p.SetValue(vms, TextHelper.GetBoolNullable(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(int))
				{
					p.SetValue(vms, TextHelper.GetInt(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(int?))
				{
					p.SetValue(vms, TextHelper.GetIntNullable(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(int[]))
				{
					if (request.Form[p.Name] != StringValues.Empty)
					{
						p.SetValue(vms, TextHelper.GetInts(request.Form[p.Name]));
					}
					else
					{
						p.SetValue(vms, TextHelper.GetInts(request.Form[p.Name + "[]"]));
					}
				}
				else if (p.PropertyType == typeof(long))
				{
					p.SetValue(vms, TextHelper.GetInt64(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(long?))
				{
					p.SetValue(vms, TextHelper.GetInt64Nullable(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(long[]))
				{
					if (request.Form[p.Name] != StringValues.Empty)
					{
						p.SetValue(vms, TextHelper.GetInt64s(request.Form[p.Name]));
					}
					else
					{
						p.SetValue(vms, TextHelper.GetInt64s(request.Form[p.Name + "[]"]));
					}
				}
				else if (p.PropertyType == typeof(decimal))
				{
					p.SetValue(vms, TextHelper.GetDecimal(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(decimal?))
				{
					p.SetValue(vms, TextHelper.GetDecimalNullable(request.Form[p.Name]));
				}
				else if (p.PropertyType == typeof(DateTime))
				{
					if (p.Name.EndsWith("_e"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeEnd(request.Form[p.Name]));
					}
					else if (p.Name.EndsWith("_s"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeStart(request.Form[p.Name]));
					}
					else
					{
						p.SetValue(vms, TextHelper.GetDateTime(request.Form[p.Name]));
					}
				}
			}
			return vms;
		}

		/// <summary>
		/// 获取get请求参数
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="request"></param>
		/// <returns></returns>
		public static T GetSearchModelFromJson<T>(this HttpRequest request, JObject paras, bool autoDTStartEnd = true)
			where T : BaseSearchModel, new()
		{
			T vms = new T();
			Type t = vms.GetType();
			var properties = t.GetProperties();
			foreach (var p in properties)
			{
				if (!p.CanWrite)
				{
					continue;
				}
				if (p.PropertyType == typeof(string))
				{
					p.SetValue(vms, TextHelper.GetString(paras, p.Name));
				}
				else if (p.PropertyType == typeof(bool))
				{
					p.SetValue(vms, TextHelper.GetBool(paras, p.Name));
				}
				else if (p.PropertyType == typeof(bool?))
				{
					p.SetValue(vms, TextHelper.GetBoolNullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int))
				{
					p.SetValue(vms, TextHelper.GetInt(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int?))
				{
					p.SetValue(vms, TextHelper.GetIntNullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int[]))
				{
					p.SetValue(vms, TextHelper.GetInts(paras, p.Name));
				}
				else if (p.PropertyType == typeof(long))
				{
					p.SetValue(vms, TextHelper.GetInt64(paras, p.Name));
				}
				else if (p.PropertyType == typeof(long?))
				{
					p.SetValue(vms, TextHelper.GetInt64Nullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(long[]))
				{
					p.SetValue(vms, TextHelper.GetInt64s(paras, p.Name));
				}
				else if (p.PropertyType == typeof(decimal))
				{
					p.SetValue(vms, TextHelper.GetDecimal(paras, p.Name));
				}
				else if (p.PropertyType == typeof(decimal?))
				{
					p.SetValue(vms, TextHelper.GetDecimalNullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(DateTime))
				{
					if (autoDTStartEnd)
					{
						if (p.Name.EndsWith("_e"))
						{
							p.SetValue(vms, TextHelper.GetDateTimeEnd(paras, p.Name));
						}
						else if (p.Name.EndsWith("_s"))
						{
							p.SetValue(vms, TextHelper.GetDateTimeStart(paras, p.Name));
						}
						else
						{
							p.SetValue(vms, TextHelper.GetDateTime(paras, p.Name));
						}
					}
					else
					{
						p.SetValue(vms, TextHelper.GetDateTime(paras, p.Name));
					}
				}
			}
			return vms;
		}

		public static UserSession GetSessionFromRequest(this HttpRequest request)
		{
			try
			{
				string _skey = request.Cookies["skey"];
				string _ucode = request.Cookies["ucode"];
				if (string.IsNullOrEmpty(_skey) || string.IsNullOrEmpty(_ucode))
				{
					_skey = request.Headers["skey"];
					_ucode = request.Headers["ucode"];
				}
				if (string.IsNullOrEmpty(_skey) || string.IsNullOrEmpty(_ucode))
				{
					_skey = request.Form["_skey"];
					_ucode = request.Form["_ucode"];
				}
				if (string.IsNullOrEmpty(_skey) || string.IsNullOrEmpty(_ucode))
				{
					throw new AuthException("获取会话信息为空，用户可能未登录或登录已过期");
				}
				string sessionStr = EncryptHelper.AESDecrypt(_skey, _ucode);//会话都是更新之后的
				if (string.IsNullOrEmpty(sessionStr))
				{
					throw new AuthException("解密请求头部认证信息失败，用户可能未登录或登录已过期");
				}
				var result = JsonConvert.DeserializeObject<UserSession>(sessionStr);
				if (result == null)
				{
					throw new AuthException("解析请求头部认证信息为空，登录可能已过期");
				}
				return result;
			}
			catch (AuthException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new AuthException("获取请求头部认证信息失败，用户可能未登录或登录已过期", ex);
			}
		}
	}
}
